#include <windows.h>
#include "../timer/chrtimer.h"
#include "../typedefs/typedefs.h"
#include "../adtype/cdynamicarray.h"
#include "../macros/assertions.h"

namespace NEngine {

// ================================================================================================
// Class that handles input
// ================================================================================================
class CInputHandler {

protected: 

    enum {
        eAKey = 0x41,
        eCKey = 0x43,
        eDKey = 0x44,
        eSKey = 0x53,
        eWKey = 0x57,
        eTKey = 0x54,
    };

protected:

    CStopWatch stpwtch; // -- high resolution stop watch
    POINT startpt;      // -- start pt
    POINT center;       // -- center pt
    POINT endpt;        // -- end point
    bool kill;          // -- process escape
    float mousescale;   // -- speed of mouse movement
    bool usemouse;      // -- toggle mouse movement
    RECT rect;          // -- viewport rectangle
    double deltime;     // -- time before last mouse toggle

    // -- mouse uses
    virtual void ToggleMouse(bool toggle) = 0;
    virtual void ListenMouse() = 0;
    
public:

    // -- default constructor and destructor
    CInputHandler();
    ~CInputHandler();
    
    // -- mutators
    void SetRect(const RECT& rect);

    // -- listen to message
    virtual bool Listen() = 0;
};

// ================================================================================================
// Constructor
// ================================================================================================
inline CInputHandler::CInputHandler() : kill(false), deltime(0.05), mousescale(0.002f), 
                                        usemouse(false) {
}

// ================================================================================================
// Destructor
// ================================================================================================
inline CInputHandler::~CInputHandler() {
    ShowCursor(true);
    ClipCursor(NULL);
}

// -- forward decleration
class CCamera;

// === CInputHandler ==============================================================================

// ================================================================================================
// Mutators
// ================================================================================================
inline void CInputHandler::SetRect(const RECT& rect_) {
    rect = rect_;
}

// ================================================================================================
// Camera input handler
// ================================================================================================
class CCameraInputHandler : public CInputHandler {

protected:

    ushort numcameras;             // -- index to camera
    uint camindex;                 // -- camera receiving input
    CCamera* base;                     // -- base offset to camera
    CCamera** curcam;              // -- camera that receives input

    virtual void ToggleMouse(bool toggle);
    virtual void ListenMouse();

public:

    // -- default constructor
    CCameraInputHandler();

    // -- accessor
    CCamera** GetCurCamera();

    // -- mutators
    void SetCamera(CCamera*& cam, uint numcams);

    // -- listen to input for the camera
    virtual bool Listen();
};

// ================================================================================================
// Default constructor
// ================================================================================================
inline CCameraInputHandler::CCameraInputHandler() : curcam(NULL), camindex(0),
                                                    numcameras(0), CInputHandler() {
    stpwtch.StartClock();
}

// === CCameraInputHandler ========================================================================

// ================================================================================================
// Accessors
// ================================================================================================
inline CCamera** CCameraInputHandler::GetCurCamera() {
    return curcam;
}

// ================================================================================================
// Mutators 
// ================================================================================================
inline void CCameraInputHandler::SetCamera(CCamera*& curcam_, uint numcams) {
    ASSERT_(numcams, "No valid cameras given");
    numcameras = numcams;
    curcam = &curcam_;
    base = curcam_;
}

} // namespace NEngine
